#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"

#include "clang/Tooling/ASTDiff/ASTDiff.h"
#include "clang/Analysis/AnalysisDeclContext.h"

#include<fstream>
#include<iostream>
#include<cstring>
#include<stdlib.h>
#include<sstream>
#include<fstream>
#include<dirent.h>
#include<string>
#include<time.h>

using namespace std;
using namespace std;
using namespace clang;
using namespace llvm;

int filesnum=0;
int classnamei=0;
static int len=0,sj=0;
 char **ai=new  char*[100];
struct relationship
{
	char* son;
	char* father;
};
relationship newre[20];
relationship re[20];

static int newrei=0;

	int flag1=0,flag2=0;
	int a[10]={0,0,0,0,0,0,0,0,0,0};
 
#define MAX_VERTEX_NUM 20
bool visited[20];//用于遍历时辅组使用
int Vex_Num;//统计输出顶点数目

void saveClassName(const char* allclassname,int flag);


//表结点
struct ArcNode
{
	int adjvex; //弧所指向顶点的位置
	ArcNode *nextarc;// 指向下一条弧
};
 
//头结点
typedef struct VNode
{
	string data;//顶点名
	ArcNode *firstarc;//指向第一条关联顶点的弧
}AdjList[MAX_VERTEX_NUM];
 
struct ALGraph
{
	AdjList vertices;//头结点数组
	int vexnum;//顶点数
	int arcnum;//边数
};
 
int Locate_Vex(ALGraph G,string x) //定位顶点位置
{
	int v;
	for(v=0;v<G.vexnum;v++)
	{
		if(G.vertices[v].data==x)
		{
			return v;
		}
	}
	return v;
}

void AddVexnum(ALGraph &G,int vexnum,int arcnum)   //增加顶点数量和边数
{
	G.vexnum=vexnum;
	G.arcnum=arcnum;
}


int AddVexname(ALGraph &G,int i,string name)   //增加顶点名称
{

		int j;
		for(j=0;j<G.vexnum;j++)
		{
			if(G.vertices[j].data==name)
			{
				cout<<"Vexname Repetition"<<endl;
				return 1;  //返回1是异常情况：有顶点名称重复了
			}
		}
		G.vertices[i].data=name;
		G.vertices[i].firstarc=NULL;
		return 0;
}

int examineArc(ALGraph &G,string v1,string v2)  //检查新增的边是否已存在，是否指向节点自己
{
	int i,j;
	i=Locate_Vex(G,v1);
	j=Locate_Vex(G,v2);
	if(i==j)  //是指向自己的环
	{
		cout<<"Arc Own"<<j<<endl;
		return 1;  //边重复了，返回1
	}
	//如果节点指向的边表里有过某条边，就不要再记一次了
	ArcNode *p;
	cout<<"i: "<<i<<" j: "<<j<<endl;
	p=G.vertices[i].firstarc;
	if(p)
	{
		while(p->nextarc)
		{
			if(p->nextarc->adjvex==j)
			{
				cout<<"Arc Repetition"<<j<<endl;
				return 1;  //边重复了，返回1
			}
			else
				p=p->nextarc;
		}
		if(p->adjvex==j)
		{
			cout<<"Arc Repetition"<<j<<endl;
			return 1;  //边重复了，返回1
		}
		
	//需要firstarc/p->nextarc
	}
	return 0;
}

int CreateDG_ALG(ALGraph &G,int k,string v1,string v2)	//新增边的关系
{

		int i,j;
		i=Locate_Vex(G,v1);
		j=Locate_Vex(G,v2);
		cout<<"i: "<<i<<"j: "<<j<<endl;
		if(i==G.vexnum||j==G.vexnum)
		{
			cout<<"Not Find Vex"<<endl;
			return 1;     //异常情况，新增了未知顶点的边，直接返回
		}
	
		ArcNode *p=new ArcNode;   //表节点
		p->adjvex=j;    //弧所指向顶点的位置
		cout<<i<<"  adjvex   "<<p->adjvex<<endl;
		//尾插法	
//		G.vertices[i].firstarc->nextarc=p;
//		G.vertices[i].firstarc=p;
		//头插法
		p->nextarc=G.vertices[i].firstarc;  // 指向下一条弧  ---指向第一条关联顶点的弧
		G.vertices[i].firstarc=p;   //指向第一条关联顶点的弧
	return 0;
}


string findDirectInherite(ALGraph G,string v1,string v2) //看v1和v2之间是否有直接继承关系
{
	int i,jv1,jv2;
	string result ="No Direct Inherit";
	for(i=0;i<G.vexnum;i++)
	{
		if(G.vertices[i].data==v1)
		{
	//		cout<<i<<endl;
			jv1=i;
		}
		if(G.vertices[i].data==v2)
		{
//		cout<<i<<endl;
			jv2=i;
		}
	}

	ArcNode *p;	
	p=G.vertices[jv1].firstarc;
	while(p)
	{
//		cout<<"jv1 p "<<p->adjvex<<endl;
		if(p->adjvex==jv2)
		{
		                              //在a的边表节点中找，如果节点是b，找到了就跳出
			result=v1+" inherit "+v2;
			return result;
		}
			p=p->nextarc;
		
	}

	p=G.vertices[jv2].firstarc;
	while(p)
	{
	//		cout<<"jv2 p "<<p->adjvex<<endl;
		if(p->adjvex==jv1)
		{
			result=v2+" inherit "+v1;
			return result;
		}
			p=p->nextarc;
	}
	
	return result;
}
 
void fun(ALGraph G,int locv1,int locv2,int v12,int ai)
{
	
	a[ai]=locv1;
	cout<<"ai:          "<<ai<<endl;
	  cout<<"a[ai]1: "<<a[ai]<<endl; 
	ArcNode *p=G.vertices[locv1].firstarc;
	if(p)
	{
	/*	if(p->adjvex==locv1)
		{
			cout<<"circle"<<endl; //避免出现（a,a）的情况，一直查询自己的边表，死循环
			return;
		}
	*/
		if(p->adjvex==locv2)
		{
			ai++;
			a[ai]=locv2;
	//		cout<<"yyyyyyyyyyyyes"<<endl;
			if(v12==12)
				flag1=1;
			if(v12==21)
				flag2=1;
		}
		else
		{	
			fun(G,p->adjvex,locv2,v12,++ai);
		}
		if(flag1==1||flag2==1) //若在本节点某条边指向的其他节点查到了要找的节点，不用再查本节点的其他边了
		{
			return;
		}
		else
		{
			while(p->nextarc)
			{
				p=p->nextarc;
				if(p->adjvex==locv2)
				{
					ai++;
					a[ai]=locv2;
	//				cout<<"yyyyyyyyyyyyes"<<endl;
					if(v12==12)
						flag1=1;
					if(v12==21)
						flag2=1;
				}
				else
					fun(G,p->adjvex,locv2,v12,++ai);
			}
		}
	}
	if(flag1==0&&flag2==0)
	{
		a[ai]=0;
	}
	   cout<<"a[ai]2: "<<a[ai]<<endl;

}

string findIndirectInherite(ALGraph G,string v1,string v2) //看v1和v2之间是否有（直接/间接）继承关系
{
	int i,locv1,locv2;

	string result ="No Inherit";
	for(i=0;i<G.vexnum;i++)
	{
		if(G.vertices[i].data==v1)  //v1的节点位置
		{
			
			locv1=i;
		}
		if(G.vertices[i].data==v2)  //v2的节点位置
		{
		
			locv2=i;
		}
	}

	fun(G,locv1,locv2,12,0);

cout<<"flag1: "<<flag1<<" flag2: "<<flag2<<endl;
    if(flag1==1)  //如果正向查到了继承关系，就不用反向查了
	{
		result=v1+" (Indirect) Inherit "+v2;
	}
	else //正向没查到就反向查
	{
		fun(G,locv2,locv1,21,0);
		cout<<"fffffffffffffffffffff"<<endl;
	
		if(flag2==1) //如果反向查到了，就输出结果
		{
			result=v2+" (Indirect) Inherit "+v1;
		}
		else  //如果反向没查到，继承路径全部置为0
		{
			for(i=1;i<10;i++)
			{
				a[i]=0;
			}
		}
	}
	return result;
}

void Show(ALGraph G)
{
	int i,j;
	ArcNode *p;
	for(i=0;i<G.vexnum;i++)
	{
		cout<<G.vertices[i].data<<"("<<i<<")"<<": ";
		p=G.vertices[i].firstarc;  //首先指向节点的第一条边
		if(p)    //如果节点有第一个边，就输出边指向的节点，否则调到下一个节点
		{
			cout<<p->adjvex<<"  ";
			while(p->nextarc)    //如果节点有第2、3、4、5...个边，就分别输出这些边指向的节点
			{
				p=p->nextarc;
				cout<<p->adjvex<<"  ";
			
			}
		}
		cout<<endl;
	}
}

 



class FindNamedClassVisitor : public RecursiveASTVisitor<FindNamedClassVisitor> {
public:
	string abc;
   explicit FindNamedClassVisitor(ASTContext *Context)
    : Context(Context) {	abc="asd";}

string getabc()
{
	cout<<"-------  "<<this->abc<<endl;
	return (this->abc);
}

bool VisitCXXRecordDecl(CXXRecordDecl *Declaration) {
//	   Declaration->dumpColor();    //彩色打印AST内容
    		 llvm::outs() <<"ClassName:  "<<Declaration->getNameAsString()<<"\n";   //类名称
			const char* chr=(Declaration->getNameAsString()).c_str();
		//		const char* dot=const_cast<char *>(chr);
			saveClassName(chr,1);
		//	 	   llvm::outs() <<"getDeclKind: "<<Declaration->getDeclKind()<<"\n";     //节点类型编号
				   		 //llvm::outs() <<"isDerivedFrom: "<<Declaration->isDerivedFrom()<<"\n";    //是否是谁的基类，不知道参数怎么写，没用过
		//		   	   llvm::outs() <<"getParentName: "<<(Declaration->getParent())->getDeclKindName()<<"\n";   //父母节点的名称
			//		 	   llvm::outs() <<"getLexicalParentName: "<<(Declaration->getLexicalParent())->getDeclKindName()<<"\n";   //文法父母的名称
		//			    	   llvm::outs() <<"getLookupParentName: "<<(Declaration->getLookupParent())->getDeclKindName()<<"\n";  //找父母节点的名字
			//					 llvm::outs() <<"bases_begin: "<<(Declaration->bases_begin())->getNameAsString()<<"\n";	     //语法错误，基类迭代器类型是Specifier，不能用getnameasstring()方法
			       for(clang::CXXRecordDecl::base_class_iterator dit=Declaration->bases_begin();dit!=Declaration->bases_end();dit++)//基类迭代器，类型是Specifier
			  {	   
            //       cout<<"base__isBaseOfClass:"<<dit->isBaseOfClass()<<endl; //是否是谁的基类，没什么用
			//	   cout<<"base__isVirtual:"<<dit->isVirtual()<<endl;  //是否为虚基类
			//	   		  cout<<"gettype:"<<endl;    //获取节点的类型
		//        	(dit->getType())->dump();   //打印全部AST内容
		       const char* ch=(((dit->getType())->getAsCXXRecordDecl())->getNameAsString()).c_str();
				 cout<<"BaseClassName:  "<<ch<<endl;
				 saveClassName(ch,2);
//				 ((dit->getType())->getAsCXXRecordDecl())->getNameAsString()<<endl;
			//	  cout<<(dit->getType())->getTypeClassName()<<endl;   //获取类型名称
		//		  cout<<"gettype:"<<dit->getType()<<endl; 
	
			  }
			  		 cout<<"abcCCCCCCCCCCCCCCC"<<getabc()<<endl;
	this->abc="string";
		 cout<<"abcCCCCCCCCCCCCCCC"<<getabc()<<endl;
		//	 cout<<"abcCCCCCCCCCCCCCCCCCCCCCCCCCCC  "<<this->abc<<endl;
			 return true;
}

private:
  ASTContext *Context;
};

class FindNamedClassConsumer : public clang::ASTConsumer {
public:
  explicit FindNamedClassConsumer(ASTContext *Context)
    : Visitor(Context) {}

  virtual void HandleTranslationUnit(clang::ASTContext &Context) {
    Visitor.TraverseDecl(Context.getTranslationUnitDecl());
  }
  
  FindNamedClassVisitor GetVisitorString()
  {
	  cout<<"aaaaaaaaaaaaaaaaaaaaaaa"<<Visitor.getabc()<<endl;
  }
	
	FindNamedClassVisitor& getVisitor()
	{
		return Visitor;
	}
  
private:
  FindNamedClassVisitor Visitor;
};

class FindNamedClassAction : public clang::ASTFrontendAction {
public:
	//FindNamedClassAction *fnc;
	//FindNamedClassAction()
//	{ 
	//	fnc=new FindNamedClassConsumer(&Compiler.getASTContext();
	//}
   FindNamedClassConsumer *fncc;

  virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(
    clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
		fncc=new FindNamedClassConsumer(&Compiler.getASTContext());
    return std::unique_ptr<clang::ASTConsumer>(fncc );
 //return std::unique_ptr<clang::ASTConsumer>( *fnc);
  }	
};

char **readFileName(const char *folderpath)
{
	char *newpath=new char[50];
	strcpy(newpath,folderpath);
	char **namelist;
	DIR *dp;
	struct dirent *dirp;
	int n,i,j;
	namelist=(char **)malloc(20*sizeof(char *));
	for(i=0;i<20;i++)
	{
		namelist[i]=(char *)malloc(256*sizeof(char));
	}
	
	if((dp=opendir(folderpath))==NULL)
	{
		cout<<"can't open folder"<<endl;
	}
	i=0;
	while(((dirp=readdir(dp))!=NULL)&&(n<50))
	{
	
		if(memcmp(".",dirp->d_name,1)==0)
		{
			//忽略.和..文件
		}
		else
		{
			memcpy(namelist[i],dirp->d_name,20);
			strcat(newpath,namelist[i]);
			strcpy(namelist[i],newpath);
			strcpy(newpath,folderpath);
			i++;
			filesnum++;
		}
	}
	closedir(dp);
	return namelist;
}

void findAST(char **filenames)
{
	int i,j;
	for(i=0;i<filesnum;i++)
	{
		ifstream ifile;
		string s="",sum="";
		ifile.open(filenames[i]);
		if(!ifile.is_open())
		{
			cout<<"error opening file!"<<endl;
			return;
		}
		while(!ifile.eof())
		{
			getline(ifile,s);
			sum=sum+s+"\n";
			cout<<"s: "<<s<<endl;
		}
	
//  	cout<<"sum: "<<sum<<endl;
	ifile.close();  
  	int m;
	auto fc=make_unique<FindNamedClassAction>();
	m=clang::tooling::runToolOnCode(move(fc), sum);
  //m=clang::tooling::runToolOnCode(fc, sum);  make_unique<FindNamedClassAction>(fc.get()
  //cout << *fc << endl;
	}
}

void saveClassName(const char* allclassname,int flag)
{
	char* pc=new char[100];
	strcpy(pc,allclassname); 
cout<<"classnamei   "<<classnamei<<endl;
if(flag==1)
{
	 strcpy(ai[classnamei],pc);
      cout<<"ai[classnamei]  "<<ai[classnamei]<<endl;
 	  cout<<"classnamei "<<classnamei++<<endl;
 //	  strcpy(newre[newrei].son,pc);
 //	  cout<<"newrei  "<<newrei++<<endl;
}
else
{

}
//ai[classnamei]=(char *)malloc(50*sizeof(char));
  
//	strcpy(ai[0],allclassname);
//	classname[classnamei]=className;
//	classnamei++;
//	cout<<"classname[][][]: "<<ai[0]<<endl;

ofstream outfile;
if(!outfile)
{
	cout<<"no file"<<endl;
}
outfile.open("/home/song/llvm-project/record/record.txt",ios::app);
if(flag==1)
outfile<<"1,"<<allclassname<<endl;
else
{
	outfile<<"2,"<<allclassname<<endl;
}
}

char** readBaseClassName()
{
	ifstream inFile("/home/song/llvm-project/record/record.txt",ios::in);
	std::string lineStr;
	char**list1,**list2,**list3;
	int i,j,k,flag=0,n=0,m=0;
	list1=(char **)malloc(100*sizeof(char *));
	for(i=0;i<100;i++)
		list1[i]=(char *)malloc(256*sizeof(char));

	list2=(char **)malloc(30*sizeof(char *));
	for(i=0;i<30;i++)
		list2[i]=(char *)malloc(256*sizeof(char));

		list3=(char **)malloc(30*sizeof(char *));
	for(i=0;i<30;i++)
		list3[i]=(char *)malloc(256*sizeof(char));
//getline(inFile,lineStr);

      for(i=0;i<100;i++)
          {
          	list1[i]="";
	//cout<<"list2[]"<<list1[i]<<endl;
          }
 i=0;
 
	while(getline(inFile,lineStr))
	{
		n++;
		cout<<"linestr:     "<<lineStr<<endl;
		const char *line=lineStr.c_str();
		char *pc=new char[100];
		strcpy(pc,line);
		cout<<"len nnn="<<len<<endl;
       if(len==0)
     {
     	list1[0]=pc;
     	len++;
     }
     else
     {
     	flag=0;
         for(j=0;j<len;j++)
         {
         	if(strcmp(list1[j],pc)==0)
         		flag=1; //表示该类名已经存过
         }
         if(flag==0)
         {
     		list1[len]=pc;
           len++;
         }
     }

           i++;
      
	cout<<"iiiii "<<i<<endl;
	cout<<"nnnnn "<<n<<endl;
		cout<<"flag "<<flag<<endl;

}


for(i=0;i<len;i++)
{
		cout<<"list2  "<<i<<"  "<<list1[i]<<endl;
	
}


	inFile.close();
for(i=0;i<n;i++)
{
   if(strcmp(list1[0],list1[i])==0)
   	m++;  //如果有重复就计数
}
cout<<"mmmmmm"<<m<<endl;

for(i=0,sj=0;i<len;i++)
{
	//re[0].father=list1[0];
	//re[0].son=list1[0];
	if(list1[i][0]=='1'&&list1[i+1][0]=='2')
	{
		//strcpy(re[sj].son,list1[i]);
		//strcpy(re[sj].father,list1[i+1]);
	re[sj].son=list1[i];
	re[sj].father=list1[i+1];
		sj++;
		i++;
		i++;
	}

	if(list1[i][0]=='1'&&list1[i+1][0]!='2')
 	{

	}
	if(list1[i][0]=='2')
	{
		//strcpy(re[sj].son,re[sj-1].son);
		//strcpy(re[sj].father,list1[i]);

		re[sj].son=re[sj-1].son;
		re[sj].father=list1[i];

		sj++;
	}

}
//re[0].son="asd";


for(i=0;i<len;i++)
{
	strcpy(list3[i],list1[i]);
	cout<<"list3  "<<list3[i]<<endl;
}


return list3;
}
	

int main(int argc, char **argv) 
{
	int i,j;
	string s="";
	char **list2,**list4;
	string sum="";
	const char *filepath="/home/song/llvm-project/test/father.hpp";
	//filepath=argv[1];
	cout<<"文件名："<<filepath<<endl;
	//char **classname;
	//classname=(char **)malloc(20*sizeof(char *));
	for(classnamei=0;classnamei<20;classnamei++)
	{
		ai[classnamei]=new char[64];
		ai[classnamei]=(char *)malloc(50*sizeof(char));
	}
	classnamei=0;
  
	char **filenames=readFileName(argv[1]);
	for(i=0;i<filesnum;i++)
	{
			cout<<"文件名列表："<<filenames[i]<<endl;
	}
	findAST(filenames);
	
	for(i=0;i<classnamei-1;i++)
	{
		cout<<"Result："<<classnamei<<"  "<<i<<"    "<<ai[i]<<endl;
	}

	list2=readBaseClassName();

		list4=(char **)malloc(30*sizeof(char *));
	for(i=0;i<30;i++)
		list4[i]=(char *)malloc(256*sizeof(char));

    for(i=0;i<len;i++)
    {
    	for(j=2;j<strlen(list2[i]);j++)
    	{
    		list4[i][j-2]=list2[i][j];
    	}
    	
    }
    	for(i=0;i<len;i++)
		{
			cout<<"list4 "<<list4[i]<<endl;
		}


	for(i=0;i<sj;i++)
{
/*	for(j=2;j<strlen(re[i].son);j++)
	{
        newre[i].son[j-2]=re[i].son[j];
	}

	for(j=2;j<strlen(re[i].father);j++)
	{
        newre[i].father[j-2]=re[i].father[j];
	}

cout<<newre[0].son<<endl;

//cout<<"newre.son "<<newre[i].son<<" "<<"  newre,father "<<newre[i].father<<endl;
*/

cout<<"re.son "<<re[i].son<<" "<<"  re,father "<<re[i].father<<endl;
}
	/*
	ifstream ifile;
	ifile.open(filepath);
	if(!ifile.is_open())
	{
		cout<<"error opening file!"<<endl;
	}

	while(!ifile.eof())
	{
		getline(ifile,s);
		sum=sum+s+"\n";
		cout<<s<<endl;
	}
  	cout<<sum<<endl;
	ifile.close();  
  
 	if (argc > 1) 
	{
		char *a="namespace  n {class C {   };  }";
	//	clang::tooling::runToolOnCode(std::make_unique<FindNamedClassAction>(), sum);
	}
   */

	ALGraph G;
	int vexnum;
	int exam=0;
	string v1,v2;
	int sumvex;
	char **data;
	
	data=(char **)malloc(20*sizeof(char *));
	for(i=0;i<20;i++)
	{
		data[i]=(char *)malloc(256*sizeof(char));
	}

	cout<<"输入顶点数：";
	vexnum=len;
	AddVexnum(G,vexnum,sj); //新增顶点数量

	//构造头结点数组
	cout<<"输入顶点名称：";
	cout<<G.vexnum<<" "<<endl;
	sumvex=0;
    for(i=0;i<G.vexnum;i++)
	{
		strcpy(data[i],list4[i]);
     	int add;
		add=AddVexname(G,i,data[i]);  //新增顶点名称
		if(add==1)  //有异常就不保存，继续新增
		{
			sumvex++;
		//	i--;
		//	continue;
		}
	}
	sumvex=len-sumvex;
    G.vexnum=sumvex;
	//输入各弧并构造邻接表
    for(i=0;i<sj;i++)
	{
		cout<<"按尾->头的顺序输入边所对应的两个顶点：";
		v1=re[i].son;
		v2=re[i].father;
		string c="";
		for(j=2;j<strlen(re[i].son);j++)
		{
			c=c+v1[j];
		}
		v1=c;
		c="";
		//cout<<" c "<<c<<endl;
		for(j=2;j<strlen(re[i].father);j++)
		{
			c=c+v2[j];
		}
		v2=c;
        c="";
		exam=examineArc(G,v1,v2);  //检查新增的边是否已经存在,新增的边是否指向节点自己
		if(exam==1)
		{
		//	i--;
	//		continue;  //若已经存在，不存这条边，继续新增
		}
		else
		{
			int add;
    		add=CreateDG_ALG(G,i,v1,v2);  //新增边的关系
			if(add==1)
				return 0;
		}
	}

	cout<<"输入两个要查询关系的类：";
    cin>>v1>>v2;
    string resultdirect=findDirectInherite(G,v1,v2);  //看v1和v2之间是否有直接继承关系
    string resultindirect=findIndirectInherite(G,v1,v2);  //看v1和v2之间是否有间接继承关系
    cout<<resultdirect<<endl;
    cout<<resultindirect<<endl;
	
	cout<<"继承关系图："<<endl;
	Show(G);

	cout<<"继承路径："<<endl;
	int k=0;
	for(k=0;k<10;k++)
	{
		cout<<a[k]<<" ";
	}
	cout<<endl;


	return 0;
}